/*
Copyright 2010 Iain Surgey.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

finalvert_t		fv[2][8];

finalvert_t *pf0, *pf1;

#__body__


/*
================
R_Alias_clip_z

pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex
================
*/
private function R_Alias_clip_z (out : Int) 
{
	#{s| finalvert_t *out}
	#{d| float		scale}

	scale = (ALIAS_Z_CLIP_PLANE - #{pf0->xyz[2]}) /
			(#{pf1->xyz[2]} - #{pf0->xyz[2]});

	#{out->xyz[0] = pf0->xyz[0] + (pf1->xyz[0] - pf0->xyz[0]) * scale};
	#{out->xyz[1] = pf0->xyz[1] + (pf1->xyz[1] - pf0->xyz[1]) * scale};
	#{out->xyz[2] = #[ALIAS_Z_CLIP_PLANE]#};

	#{out->s =	#[Std.int(]#pf0->s + (pf1->s - pf0->s) * scale)};
	#{out->t =	#[Std.int(]#pf0->t + (pf1->t - pf0->t) * scale)};
	#{out->l =	#[Std.int(]#pf0->l + (pf1->l - pf0->l) * scale)};

	R_AliasProjectAndClipTestFinalVert (out);
}

private function R_Alias_clip_left (out : Int)
{
	#{s| finalvert_t *out}
	#{d| float		scale}

	if (#{pf0->v} >= #{pf1->v} )
	{
		scale = (ord_aliasvrect_x - #{pf0->u}) /
				(#{pf1->u} - #{pf0->u});
		#{out->u  = #[Std.int(]#pf0->u  + ( pf1->u  - pf0->u ) * scale + 0.5)};
		#{out->v  = #[Std.int(]#pf0->v  + ( pf1->v  - pf0->v ) * scale + 0.5)};
		#{out->s  = #[Std.int(]#pf0->s  + ( pf1->s  - pf0->s ) * scale + 0.5)};
		#{out->t  = #[Std.int(]#pf0->t  + ( pf1->t  - pf0->t ) * scale + 0.5)};
		#{out->l  = #[Std.int(]#pf0->l  + ( pf1->l  - pf0->l ) * scale + 0.5)};
		#{out->zi = #[Std.int(]#pf0->zi + ( pf1->zi - pf0->zi) * scale + 0.5)};
	}
	else
	{
		scale = (ord_aliasvrect_x - #{pf1->u}) /
				(#{pf0->u} - #{pf1->u});
		#{out->u  = #[Std.int(]#pf1->u  + ( pf0->u  - pf1->u ) * scale + 0.5)};
		#{out->v  = #[Std.int(]#pf1->v  + ( pf0->v  - pf1->v ) * scale + 0.5)};
		#{out->s  = #[Std.int(]#pf1->s  + ( pf0->s  - pf1->s ) * scale + 0.5)};
		#{out->t  = #[Std.int(]#pf1->t  + ( pf0->t  - pf1->t ) * scale + 0.5)};
		#{out->l  = #[Std.int(]#pf1->l  + ( pf0->l  - pf1->l ) * scale + 0.5)};
		#{out->zi = #[Std.int(]#pf1->zi + ( pf0->zi - pf1->zi) * scale + 0.5)};
	}
}

private function R_Alias_clip_right (out : Int)
{
	#{s| finalvert_t *out}
	#{d| float		scale}

	if ( #{pf0->v} >= #{pf1->v} )
	{
		scale = (ord_aliasvrectright - #{pf0->u} ) /
				(#{pf1->u} - #{pf0->u} );
		#{out->u  = #[Std.int(]#pf0->u  + ( pf1->u  - pf0->u ) * scale + 0.5)};
		#{out->v  = #[Std.int(]#pf0->v  + ( pf1->v  - pf0->v ) * scale + 0.5)};
		#{out->s  = #[Std.int(]#pf0->s  + ( pf1->s  - pf0->s ) * scale + 0.5)};
		#{out->t  = #[Std.int(]#pf0->t  + ( pf1->t  - pf0->t ) * scale + 0.5)};
		#{out->l  = #[Std.int(]#pf0->l  + ( pf1->l  - pf0->l ) * scale + 0.5)};
		#{out->zi = #[Std.int(]#pf0->zi + ( pf1->zi - pf0->zi) * scale + 0.5)};
	}
	else
	{
		scale = (ord_aliasvrectright - #{pf1->u} ) /
				(#{pf0->u} - #{pf1->u} );
		#{out->u  = #[Std.int(]#pf1->u  + ( pf0->u  - pf1->u ) * scale + 0.5)};
		#{out->v  = #[Std.int(]#pf1->v  + ( pf0->v  - pf1->v ) * scale + 0.5)};
		#{out->s  = #[Std.int(]#pf1->s  + ( pf0->s  - pf1->s ) * scale + 0.5)};
		#{out->t  = #[Std.int(]#pf1->t  + ( pf0->t  - pf1->t ) * scale + 0.5)};
		#{out->l  = #[Std.int(]#pf1->l  + ( pf0->l  - pf1->l ) * scale + 0.5)};
		#{out->zi = #[Std.int(]#pf1->zi + ( pf0->zi - pf1->zi) * scale + 0.5)};
	}
}

private function R_Alias_clip_top (out : Int)
{
	#{s| finalvert_t *out}
	#{d| float		scale}

	if (#{pf0->v} >= #{pf1->v})
	{
		scale = (ord_aliasvrect_y - #{pf0->v}) /
				(#{pf1->v} - #{pf0->v});
		#{out->u  = #[Std.int(]#pf0->u  + ( pf1->u  - pf0->u ) * scale + 0.5)};
		#{out->v  = #[Std.int(]#pf0->v  + ( pf1->v  - pf0->v ) * scale + 0.5)};
		#{out->s  = #[Std.int(]#pf0->s  + ( pf1->s  - pf0->s ) * scale + 0.5)};
		#{out->t  = #[Std.int(]#pf0->t  + ( pf1->t  - pf0->t ) * scale + 0.5)};
		#{out->l  = #[Std.int(]#pf0->l  + ( pf1->l  - pf0->l ) * scale + 0.5)};
		#{out->zi = #[Std.int(]#pf0->zi + ( pf1->zi - pf0->zi) * scale + 0.5)};
	}
	else
	{
		scale = (ord_aliasvrect_y - #{pf1->v}) /
				(#{pf0->v} - #{pf1->v});
		#{out->u  = #[Std.int(]#pf1->u  + ( pf0->u  - pf1->u ) * scale + 0.5)};
		#{out->v  = #[Std.int(]#pf1->v  + ( pf0->v  - pf1->v ) * scale + 0.5)};
		#{out->s  = #[Std.int(]#pf1->s  + ( pf0->s  - pf1->s ) * scale + 0.5)};
		#{out->t  = #[Std.int(]#pf1->t  + ( pf0->t  - pf1->t ) * scale + 0.5)};
		#{out->l  = #[Std.int(]#pf1->l  + ( pf0->l  - pf1->l ) * scale + 0.5)};
		#{out->zi = #[Std.int(]#pf1->zi + ( pf0->zi - pf1->zi) * scale + 0.5)};
	}
}

private function R_Alias_clip_bottom (out : Int)
{
	#{s| finalvert_t *out}
	#{d| float		scale}

	if (#{pf0->v} >= #{pf1->v})
	{
		scale = (ord_aliasvrectbottom - #{pf0->v}) /
				(#{pf1->v} - #{pf0->v});
		#{out->u  = #[Std.int(]#pf0->u  + ( pf1->u  - pf0->u ) * scale + 0.5)};
		#{out->v  = #[Std.int(]#pf0->v  + ( pf1->v  - pf0->v ) * scale + 0.5)};
		#{out->s  = #[Std.int(]#pf0->s  + ( pf1->s  - pf0->s ) * scale + 0.5)};
		#{out->t  = #[Std.int(]#pf0->t  + ( pf1->t  - pf0->t ) * scale + 0.5)};
		#{out->l  = #[Std.int(]#pf0->l  + ( pf1->l  - pf0->l ) * scale + 0.5)};
		#{out->zi = #[Std.int(]#pf0->zi + ( pf1->zi - pf0->zi) * scale + 0.5)};
	}
	else
	{
		scale = (ord_aliasvrectbottom - #{pf1->v}) /
				(#{pf0->v} - #{pf1->v});
		#{out->u  = #[Std.int(]#pf1->u  + ( pf0->u  - pf1->u ) * scale + 0.5)};
		#{out->v  = #[Std.int(]#pf1->v  + ( pf0->v  - pf1->v ) * scale + 0.5)};
		#{out->s  = #[Std.int(]#pf1->s  + ( pf0->s  - pf1->s ) * scale + 0.5)};
		#{out->t  = #[Std.int(]#pf1->t  + ( pf0->t  - pf1->t ) * scale + 0.5)};
		#{out->l  = #[Std.int(]#pf1->l  + ( pf0->l  - pf1->l ) * scale + 0.5)};
		#{out->zi = #[Std.int(]#pf1->zi + ( pf0->zi - pf1->zi) * scale + 0.5)};
	}
}



private function R_AliasClip (vin : Int, out : Int, flag : Int, count : Int,
	clipfunc : Int->Void ) : Int
{
	#{s| finalvert_t *vin, *out}
	#{s| int flag, count}
	#{d| int			i,j,k}
	#{d| int			flags, oldflags}
	
	j = count-1;
	k = 0;
	for (i in 0...count)
	{
		oldflags = #{vin[j].flags} & flag;
		flags = #{vin[i].flags} & flag;
		
		if (flags != 0 && oldflags != 0) {
			j = i;
			continue;
		}
		if ((oldflags ^ flags) != 0)
		{
			pf0 = #{&vin[j]};
			pf1 = #{&vin[i]};
			clipfunc (#{&out[k]});
			#{out[k].flags = 0};
			if (#{out[k].u} < ord_aliasvrect_x)
				#{out[k].flags = out[k].flags | #[ALIAS_LEFT_CLIP]#};
			if (#{out[k].v} < ord_aliasvrect_y)
				#{out[k].flags = out[k].flags | #[ALIAS_TOP_CLIP]#};
			if (#{out[k].u} > ord_aliasvrectright)
				#{out[k].flags = out[k].flags | #[ALIAS_RIGHT_CLIP]#};
			if (#{out[k].v} > ord_aliasvrectbottom)
				#{out[k].flags = out[k].flags | #[ALIAS_BOTTOM_CLIP]#};	
			k++;
		}
		if (flags == 0)
		{
			CopyFV(#{&vin[i]}, #{&out[k]});
			//out[k] = vin[i];
			k++;
		}
		j = i;
	}
	
	return k;
}



/*
================
R_AliasClipTriangle
================
*/
private function R_AliasClipTriangle (index0 : Int, index1 : Int, index2 : Int)
{
	#{s| finalvert_t *index0, *index1, *index2}
	#{d| int				i, k, pingpong}
	#{d| int clipflags}
	
	
	
// copy vertexes and fix seam texture coordinates
	
	CopyFV(index0, #{&fv[0][0]});
	CopyFV(index1, #{&fv[0][1]});
	CopyFV(index2, #{&fv[0][2]});

// clip
	clipflags = #{fv[0][0].flags} | #{fv[0][1].flags} | #{fv[0][2].flags};
	
	if ((clipflags & ALIAS_Z_CLIP) != 0)
	{
		k = R_AliasClip (#{fv[0]}, #{fv[1]}, ALIAS_Z_CLIP, 3, R_Alias_clip_z);
		if (k == 0)
			return;

		pingpong = 1;
		clipflags = #{fv[1][0].flags} | #{fv[1][1].flags} | #{fv[1][2].flags};
	}
	else
	{
		pingpong = 0;
		k = 3;
	}
	
	if ((clipflags & ALIAS_LEFT_CLIP) != 0)
	{
		k = R_AliasClip (#{fv[pingpong]}, #{fv[ #[pingpong^1]#]},
							ALIAS_LEFT_CLIP, k, R_Alias_clip_left);
		if (k == 0)
			return;

		pingpong ^= 1;
	}
	
	if ((clipflags & ALIAS_RIGHT_CLIP) != 0)
	{
		k = R_AliasClip (#{fv[pingpong]}, #{fv[#[pingpong^1]#]},
							ALIAS_RIGHT_CLIP, k, R_Alias_clip_right);
		if (k == 0)
			return;

		pingpong ^= 1;
	}

	if ((clipflags & ALIAS_BOTTOM_CLIP) != 0)
	{
		k = R_AliasClip (#{fv[pingpong]}, #{fv[#[pingpong^1]#]},
							ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom);
		if (k == 0)
			return;

		pingpong ^= 1;
	}

	if ((clipflags & ALIAS_TOP_CLIP) != 0)
	{
		k = R_AliasClip (#{fv[pingpong]}, #{fv[#[pingpong^1]#]},
							ALIAS_TOP_CLIP, k, R_Alias_clip_top);
		if (k == 0)
			return;

		pingpong ^= 1;
	}
	
	for (i in 0...k)
	{
		if (#{fv[pingpong][i].u} < ord_aliasvrect_x)
			#{fv[pingpong][i].u = ord_aliasvrect_x};
		else if (#{fv[pingpong][i].u} > ord_aliasvrectright)
			#{fv[pingpong][i].u = ord_aliasvrectright};
		
		if (#{fv[pingpong][i].v} < ord_aliasvrect_y)
			#{fv[pingpong][i].v = ord_aliasvrect_y};
		else if (#{fv[pingpong][i].v} > ord_aliasvrectbottom)
			#{fv[pingpong][i].v = ord_aliasvrectbottom};
		
		#{fv[pingpong][i].flags = 0};
	}
	
// draw triangles
	for (i in 1...(k-1))
	{
		atriparms_a = #{&fv[pingpong][0]};
		atriparms_b = #{&fv[pingpong][i]};
		atriparms_c = #{&fv[pingpong][i+1]};
		R_DrawTriangle();
	}
}

private inline function CopyFV(src : Int, dest : Int) {
	Memory.setI32(dest,Memory.getI32(src));				//u
	Memory.setI32(dest+4,Memory.getI32(src+4));			//v
	Memory.setI32(dest+8,Memory.getI32(src+8));			//s
	Memory.setI32(dest+12,Memory.getI32(src+12));		//t
	Memory.setI32(dest+16,Memory.getI32(src+16));		//l
	Memory.setI32(dest+20,Memory.getI32(src+20));		//zi
	Memory.setI32(dest+24,Memory.getI32(src+24));		//flags
	Memory.setFloat(dest+28,Memory.getFloat(src+28));	//xyz[0]
	Memory.setFloat(dest+32,Memory.getFloat(src+32));	//xyz[1]
	Memory.setFloat(dest+36,Memory.getFloat(src+36));	//xyz[2]
}





